package com.forum.module.system.service.role;

import com.alibaba.nacos.shaded.com.google.common.annotations.VisibleForTesting;
import com.forum.framework.common.exception.util.ServiceExceptionUtils;
import com.forum.framework.common.pojo.PageResult;
import com.forum.framework.security.core.LoginUser;
import com.forum.framework.security.core.util.SecurityUtils;
import com.forum.module.system.controller.admin.role.vo.RolePageReqVO;
import com.forum.module.system.controller.admin.role.vo.RoleRespVO;
import com.forum.module.system.controller.admin.role.vo.RoleSaveReqVO;
import com.forum.module.system.dal.dataobject.role.RoleDO;
import com.forum.module.system.dal.dataobject.user_role.UserRoleDO;
import com.forum.module.system.dal.mysql.role.RoleMapper;
import com.forum.module.system.dal.mysql.user_role.UserRoleMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.forum.module.system.enums.ErrorCodeConstants.ROLE_NOT_EXISTS;
import static com.forum.module.system.enums.ErrorCodeConstants.USER_ROLE_NOT_EXISTS;

/**
 * 功能:
 * 作者:ouyzh
 * 日期:2025/3/15 20:45
 */
@Service
public class RoleServiceImpl implements RoleService {
    private final RoleMapper roleMapper;

    private final UserRoleMapper userRoleMapper;

    public RoleServiceImpl(RoleMapper roleMapper,
                           UserRoleMapper userRoleMapper) {
        this.roleMapper = roleMapper;
        this.userRoleMapper = userRoleMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRole(RoleSaveReqVO reqVO) {
        RoleDO roleDO = new RoleDO();

        roleDO.setName(reqVO.getName());

        roleMapper.insert(roleDO);
        return roleDO.getId();
    }

    @Override
    public void updateRole(RoleSaveReqVO reqVO) {
        RoleDO roleDO = new RoleDO();

        roleDO.setId(reqVO.getId());
        roleDO.setName(reqVO.getName());

        roleMapper.updateById(roleDO);
    }

    @Override
    public PageResult<RoleDO> getRolePage(RolePageReqVO pageReqVO) {
        return roleMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<RoleRespVO> getUserRolePage(RolePageReqVO pageReqVO) {
        PageResult<RoleDO> roleDOPageResult = roleMapper.selectPage(pageReqVO);
        PageResult<UserRoleDO> userRoleDOPageResult = userRoleMapper.selectPage(pageReqVO);

        Map<Long, String> roleMaps = roleDOPageResult
                .getList()
                .stream()
                .collect(Collectors
                        .toMap(RoleDO::getId, RoleDO::getName)
                );


        List<RoleRespVO> roleRespVOS = userRoleDOPageResult
                .getList()
                .stream()
                .map(userRoleDO -> {
                    RoleRespVO roleRespVO = new RoleRespVO();
                    roleRespVO.setId(userRoleDO.getRoleId());
                    roleRespVO.setName(roleMaps.get(userRoleDO.getRoleId()));
                    roleRespVO.setUserId(userRoleDO.getUserId());
                    return roleRespVO;
                }).toList();

        PageResult<RoleRespVO> roleRespVOPageResult = new PageResult<>();
        roleRespVOPageResult.setList(roleRespVOS);
        roleRespVOPageResult.setTotal((long) roleRespVOS.size());
        return roleRespVOPageResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long id) {
        // 1. 校验角色存在
        validateRoleExists(id);

        roleMapper.deleteById(id);

        // 1. 校验用户角色存在
        UserRoleDO userRoleDO = validateUserRoleExists(id);

        userRoleMapper.deleteById(userRoleDO.getId());
    }

    @Override
    public RoleDO selectById(Long id) {
        return roleMapper.selectById(id);
    }

    @VisibleForTesting
    RoleDO validateRoleExists(Long id) {
        if (id == null) {
            return null;
        }
        RoleDO roleDO = roleMapper.selectById(id);
        if (roleDO == null) {
            throw ServiceExceptionUtils.exception(ROLE_NOT_EXISTS);
        }
        return roleDO;
    }

    @VisibleForTesting
    UserRoleDO validateUserRoleExists(Long id) {
        if (id == null) {
            return null;
        }
        UserRoleDO userRoleDO = userRoleMapper.selectById(id);
        if (userRoleDO == null) {
            throw ServiceExceptionUtils.exception(USER_ROLE_NOT_EXISTS);
        }
        return userRoleDO;
    }
}
